#!/bin/bash
# =====================================================
# 🔄 IPA 重签名脚本
# 用法：
#   ./re_package.command appstore [ipa_path]
#   ./re_package.command testrelease [ipa_path]   # 默认模式
# 说明：
# - 必填参数：重签名类型 appstore / testrelease。
# - 可选参数：IPA 路径，不传则默认取 build/ios/ipa 下最新的 ipa。
# - 证书名可留空，脚本会依据描述文件的 TeamId 自动匹配本机已安装的证书；找不到则报错。
# - BundleId 默认为 ipa 内现有值，如需覆盖可配置下方 BUNDLE_ID。
# =====================================================

set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"

find_latest_ipa() {
  local candidates=(
    "$SCRIPT_DIR/build/ios/ipa"
    "$HOME/Desktop/casdon_build/build/ios/ipa"
  )
  for dir in "${candidates[@]}"; do
    if [[ -d "$dir" ]]; then
      echo "🔍 查找 IPA 于：$dir" >&2
      local latest
      latest=$(find "$dir" -maxdepth 1 -type f -name "*.ipa" -print0 \
        | xargs -0 ls -t 2>/dev/null \
        | head -n 1 || true)
      if [[ -n "$latest" && -f "$latest" ]]; then
        echo "$latest"
        return 0
      fi
    fi
  done
  echo ""
}

find_provision_for_bundle() {
  local target_bid="$1"
  local dirs=(
    "$HOME/Library/MobileDevice/Provisioning Profiles"
    "$HOME/Profiles"
  )
  for profiles_dir in "${dirs[@]}"; do
    [[ -d "$profiles_dir" ]] || continue
    local profiles=()
    while IFS= read -r line; do profiles+=("$line"); done < <(ls -t "$profiles_dir"/*.mobileprovision 2>/dev/null)
    for profile in "${profiles[@]}"; do
      [[ -f "$profile" ]] || continue
      local tmp
      tmp="$(mktemp)"
      /usr/bin/security cms -D -i "$profile" > "$tmp" 2>/dev/null || { rm -f "$tmp"; continue; }
      local appid
      appid=$(/usr/libexec/PlistBuddy -c "Print :Entitlements:application-identifier" "$tmp" 2>/dev/null || true)
      rm -f "$tmp"
      [[ -z "$appid" ]] && continue
      # appid 形如 TEAMID.bundleid 或 TEAMID.*
      if [[ "$appid" == *".*" ]]; then
        echo "$profile"
        return
      fi
      local app_bid="${appid#*.}"
      if [[ -n "$target_bid" && "$app_bid" == "$target_bid" ]]; then
        echo "$profile"
        return
      fi
    done
  done
  echo ""
}
# ---------- 按类型配置证书与描述文件（可留空自动匹配） ----------
APPSTORE_CERT_NAME="" # 为空则自动匹配 TeamId 的证书
APPSTORE_PROVISION_PATH="$HOME/Profiles/appstore.mobileprovision"
APPSTORE_BUNDLE_ID="" # 留空则沿用 ipa 内的 BundleId

TESTRELEASE_CERT_NAME="" # 为空则自动匹配 TeamId 的证书
TESTRELEASE_PROVISION_PATH="$SCRIPT_DIR/Profiles/adhoc.mobileprovision"
TESTRELEASE_BUNDLE_ID="" # 留空则沿用 ipa 内的 BundleId
# ----------------------------------------------------

MODE="${1:-testrelease}"
IPA_PATH_INPUT="${2:-}"

if [[ "$MODE" != "appstore" && "$MODE" != "testrelease" ]]; then
  echo "❌ 参数错误：需指定 appstore 或 testrelease"
  exit 1
fi

if [[ -z "$IPA_PATH_INPUT" ]]; then
  echo "ℹ️ 未指定 IPA，开始自动查找..."
  IPA_PATH_INPUT=$(find_latest_ipa)
  echo "ℹ️ 自动查找结果：${IPA_PATH_INPUT:-<none>}"
fi

if [[ -z "$IPA_PATH_INPUT" || ! -f "$IPA_PATH_INPUT" ]]; then
  echo "❌ 未找到 IPA 文件，请显式传入路径"
  echo "   已尝试："
  echo "   - $SCRIPT_DIR/build/ios/ipa"
  echo "   - $HOME/Desktop/casdon_build/build/ios/ipa"
  echo "   也可以手动执行: find $SCRIPT_DIR -name '*.ipa'"
  exit 1
fi
IPA_PATH_INPUT="$(cd "$(dirname "$IPA_PATH_INPUT")" && pwd)/$(basename "$IPA_PATH_INPUT")"
echo "🎯 使用 IPA：$IPA_PATH_INPUT"

case "$MODE" in
  appstore)
    CERT_NAME="$APPSTORE_CERT_NAME"
    PROVISION_PATH="$APPSTORE_PROVISION_PATH"
    BUNDLE_ID="$APPSTORE_BUNDLE_ID"
    ;;
  testrelease)
    CERT_NAME="$TESTRELEASE_CERT_NAME"
    PROVISION_PATH="$TESTRELEASE_PROVISION_PATH"
    BUNDLE_ID="$TESTRELEASE_BUNDLE_ID"
    ;;
esac

WORK_DIR="$(cd "$(dirname "$0")" && pwd)"
TMP_DIR="$WORK_DIR/.repackage_tmp"
rm -rf "$TMP_DIR"
mkdir -p "$TMP_DIR"

echo "📦 解压 IPA：$IPA_PATH_INPUT"
unzip -q "$IPA_PATH_INPUT" -d "$TMP_DIR"

APP_DIR=$(find "$TMP_DIR/Payload" -maxdepth 1 -type d -name "*.app" | head -n 1)
if [[ -z "$APP_DIR" || ! -d "$APP_DIR" ]]; then
  echo "❌ 未找到 Payload 内的 .app"
  rm -rf "$TMP_DIR"
  exit 1
fi

echo "🔖 写入新的描述文件"
if [[ ! -f "$PROVISION_PATH" ]]; then
  # 自动匹配描述文件
  DEFAULT_BID=$(/usr/libexec/PlistBuddy -c "Print :CFBundleIdentifier" "$APP_DIR/Info.plist")
  PROVISION_PATH=$(find_provision_for_bundle "$BUNDLE_ID")
  if [[ -z "$PROVISION_PATH" ]]; then
    PROVISION_PATH=$(find_provision_for_bundle "$DEFAULT_BID")
  fi
  if [[ -z "$PROVISION_PATH" ]]; then
    echo "❌ 描述文件不存在且自动匹配失败，请设置 *_PROVISION_PATH"
    rm -rf "$TMP_DIR"
    exit 1
  fi
  echo "✅ 自动匹配描述文件：$PROVISION_PATH"
fi

cp "$PROVISION_PATH" "$APP_DIR/embedded.mobileprovision"

ENTITLEMENTS_PLIST="$TMP_DIR/entitlements.plist"
echo "🔍 生成 Entitlements"
/usr/bin/security cms -D -i "$PROVISION_PATH" > "$TMP_DIR/profile.plist"
/usr/libexec/PlistBuddy -x -c "Print :Entitlements" "$TMP_DIR/profile.plist" > "$ENTITLEMENTS_PLIST"

TEAM_ID=$(/usr/libexec/PlistBuddy -c "Print :ApplicationIdentifierPrefix:0" "$TMP_DIR/profile.plist")
if [[ -z "$CERT_NAME" ]]; then
  echo "🔍 自动查找匹配 TeamId($TEAM_ID) 的证书..."
  CERT_NAME=$(security find-identity -p codesigning -v \
    | grep "$TEAM_ID" \
    | head -n1 \
    | sed 's/.*"\\(.*\\)"/\\1/')
  if [[ -z "$CERT_NAME" ]]; then
    echo "❌ 未找到与 TeamId $TEAM_ID 匹配的代码签名证书，请手动配置 CERT_NAME"
    rm -rf "$TMP_DIR"
    exit 1
  fi
  echo "✅ 使用证书：$CERT_NAME"
fi

# 如有需要覆盖 BundleId，可设置 BUNDLE_ID；留空则保持原值
if [[ -n "$BUNDLE_ID" ]]; then
  /usr/libexec/PlistBuddy -c "Set :CFBundleIdentifier $BUNDLE_ID" "$APP_DIR/Info.plist"
fi

echo "🔐 重签名 .app"
codesign --force --sign "$CERT_NAME" --entitlements "$ENTITLEMENTS_PLIST" "$APP_DIR"

echo "📦 重新打包 IPA"
cd "$TMP_DIR"
zip -qry "resign_$MODE.ipa" Payload
cd "$WORK_DIR"

OUTPUT_PATH="$WORK_DIR/resign_$MODE.ipa"
mv "$TMP_DIR/resign_$MODE.ipa" "$OUTPUT_PATH"

echo "✅ 重签完成：$OUTPUT_PATH"

# 清理
rm -rf "$TMP_DIR"
